package zgate

import (
	"znet/leaf/chanrpc"
	"errors"
	"encoding/binary"
	"znet/zconst"
	"znet/zconst/zcmd"
)


func NewProcessor(littleEndian bool) *ZProcessor {
	p 				:= new(ZProcessor)
	p.littleEndian 	= littleEndian
	p.msgInfo 		= make(map[int]*chanrpc.Server)
	return p
}
type ZProcessor struct {
	littleEndian bool
	msgInfo map[int]*chanrpc.Server
}
//
func (this *ZProcessor) SetRouter(cmd int, msgRouter *chanrpc.Server) {
	this.msgInfo[cmd] = msgRouter
}
// goroutine safe
func (this *ZProcessor) Route(msg interface{}, userData interface{}) error {
	data := msg.(*Message)
	router, ok := this.msgInfo[int(data.Cmd)]
	if ok {
		router.Go(data.Cmd,&data,userData)
	}else{
		router, ok = this.msgInfo[zcmd.CMD_ZNET_ALL]
		if ok {
			router.Go(zcmd.CMD_ZNET_ALL,data.Cmd,data,userData)
		}
	}
	return nil
}
// goroutine safe
func (this *ZProcessor) Unmarshal(data []byte) (interface{}, error) {
	if len(data) < zconst.CMD_LEN {
		return nil, errors.New("ZProcessor data too short")
	}
	// cmd
	var cmd uint16
	if this.littleEndian {
		cmd = binary.LittleEndian.Uint16(data)
	} else {
		cmd = binary.BigEndian.Uint16(data)
	}
	m 		:= &Message{}
	m.Cmd 	= cmd
	m.Data 	= data[zconst.CMD_LEN:]
	m.Data2Json()
	return m,nil
}
// goroutine safe
func (this *ZProcessor) Marshal(msg interface{}) ([][]byte, error) {
	m := msg.(*Message)
	cmd := make([]byte, zconst.CMD_LEN)
	if this.littleEndian {
		binary.LittleEndian.PutUint16(cmd, m.Cmd)
	} else {
		binary.BigEndian.PutUint16(cmd, m.Cmd)
	}
	return [][]byte{cmd,m.Data}, nil
}

